#!/bin/env/python
# -*- coding: utf8 -*-

'''Unit tests of plurk.py'''

from plurk import *
import mox
import simplejson as json
import unittest
import plurk_api


class TestPlurkProxy(unittest.TestCase):
#class TestPlurkProxy(mox.MoxTestBase):

  def setUp(self):
    self.mox = mox.Mox()
    self.api = self.mox.CreateMock(plurk_api.PlurkAPI)
    self.proxy = PlurkProxy(self.api, json.loads)
    self.username = 'somebody'
    self.password = 'whatever'

  def tearDown(self):
    self.mox.VerifyAll()

  def testGettersWhenNoError(self):
    api_data = open('testdata/profile.api').read()
    self.api('/Users/login', True, username=self.username, 
             password=self.password).AndReturn(
             (200, api_data))
    self.mox.ReplayAll()
    user = self.proxy.Login(self.username, self.password)
    self.assertEquals('', self.proxy.GetErrorText())
    self.assertEquals(200, self.proxy.GetStatusCode())

  def testGettersWhen400Error(self):
    self.api('/Users/login', True, username=self.username, 
             password=self.password).AndReturn(
             (400, '{"error_text": "Invalid login"}'))
    self.mox.ReplayAll()
    user = self.proxy.Login(self.username, self.password)
    self.assertEquals(400, self.proxy.GetStatusCode())
    self.assertEquals({'error_text': 'Invalid login'},  self.proxy.GetResult())
    self.assertEquals('Invalid login', self.proxy.GetErrorText())

  def testGettersWhenInvalidResult(self):
    self.api('/Users/login', True, username=self.username, 
             password=self.password).AndReturn(
             (400, '{"something": "Invalid login"}'))
    self.mox.ReplayAll()
    user = self.proxy.Login(self.username, self.password)
    self.assertEquals('', self.proxy.GetErrorText())
    self.assertEquals(400, self.proxy.GetStatusCode())

  def testMakeOptions(self):
    self.assertEquals({'offset': '2009-10-10T00:00:00'},
        self.proxy._MakeOptions(
          {'offset': datetime.datetime(2009, 10, 10), 'limit': 10},
          {'offset': jsonizer.conv_datetime}))
    self.assertEquals({'offset': '2009-10-10T00:00:00', 'limit': 10},
        self.proxy._MakeOptions(
          {'offset': datetime.datetime(2009, 10, 10), 'limit': 10},
          {'offset': jsonizer.conv_datetime, 'limit': jsonizer.identity}))

  def testGetPublicProfile(self):
    python_data = PlurkUser(eval(open('testdata/profile.golden').read()))
    api_data = open('testdata/profile.api').read()
    self.api('/Profile/getPublicProfile', False,
             user_id=self.username).AndReturn((200, api_data))
    self.mox.ReplayAll()
    profile = self.proxy.GetPublicProfile(self.username)
    self.assertEquals(python_data, profile)

  def testValidLogin(self):
    python_data = PlurkUser(eval(open('testdata/profile.golden').read()))
    api_data = open('testdata/profile.api').read()
    self.api('/Users/login', True, username=self.username, 
             password=self.password).AndReturn(
             (200, api_data))
    self.mox.ReplayAll()
    result = self.proxy.Login(self.username, self.password)
    self.assertEquals(python_data, result)

  def testInvalidPasswordFailsLogin(self):
    wrong_password = 'arbitrary_string'
    self.api('/Users/login', True, username=self.username, 
             password=wrong_password).AndReturn(
             (400, '{"error_text": "Invalid login"}'))
    self.mox.ReplayAll()
    user = self.proxy.Login(self.username, wrong_password)
    self.assertEquals(None, user)
    self.assertEquals(400, self.proxy.GetStatusCode())
    self.assertEquals('Invalid login', self.proxy.GetErrorText())

  def testPlurkPostList(self):
    api_data = open('testdata/plurkpostlist.api').read()
    dic = eval(open('testdata/plurkpostlist.golden').read())
    python_data = PlurkPostList(dic['plurks'], dic['plurk_users'].values())
    since = datetime.datetime(2009, 10, 10)
    self.api('/Polling/getPlurks', False, offset=jsonizer.conv_datetime(since)
        ).AndReturn((200, api_data))
    self.mox.ReplayAll()
    result = self.proxy.GetNewPlurks(since)
    self.assertEquals(python_data, result)

#
#  def testUpdatePicture(self):
#    pass
#
#  def testUpdateUserInfo(self):
#    pass
#
#  def testGetOwnProfile(self):
#    pass
#
#  def testGetPlurks(self):
#    pass

class TestUserInfo(unittest.TestCase):

  def setUp(self):
    self._mocker = mox.Mox()
    self._proxy = self._mocker.CreateMock(PlurkProxy)
    self._nickname = 'testuser'

  def tearDown(self):
    pass

  def notatestConnectionFailureRaises(self):
    self._proxy.GetPublicProfile(self._nickname).AndRaise(
        FailToConnectError('%s: mock for no connections' % self._nickname))
    self._mocker.ReplayAll()
    self.assertRaises(FailToConnectError, UserInfo, self._nickname, self._proxy)
    self._mocker.VerifyAll()

  def notatestUserNotFoundRaises(self):
    self._proxy.GetPublicProfile(self._nickname).AndReturn(
        'whatever <h2>%s is not found!</h2> no matter' % self._nickname)
    self._mocker.ReplayAll()
    self.assertRaises(AccountNotFoundError, UserInfo, self._nickname, self._proxy)
    self._mocker.VerifyAll()

  def notatestInvalidFormatRaises(self):
    self._proxy.GetPublicProfile(self._nickname).AndReturn('whatever is the content')
    self._mocker.ReplayAll()
    self.assertRaises(FailToParseError, UserInfo, self._nickname, self._proxy)
    self._mocker.VerifyAll()

  def notatestCorrectlyParseDictionaries(self):
    self._proxy.GetPublicProfile(self._nickname).AndReturn(_test_profile_page)
    self._mocker.ReplayAll()
    user = UserInfo(self._nickname, self._proxy)
    self.assertEquals({'search_me': 0, 'message_me': 0, 'global_filter': '{}',
                       'user_id': 3158525, 'show_location': 1, 'view_plurks': 0, 
                       'sound_mute': 1}, 
                      user.settings)
    self.assertEquals({'display_name': 'luse', 'uid': 3329352, 'nick_name': 'luse',
                       'has_profile_image': 1, 'location': 'Hsinchu, Taiwan', 
                       'avatar': 0, 'full_name': 'luse cheng', 'gender': 1, 
                       'timezone': None, 'id': 3329352, 'karma': 86.47},
                      user.friends['3329352'])
    self.assertEquals({'display_name': 'Miles', 'uid': 4163456,
                       'nick_name': 'mileswang', 'has_profile_image': 1, 
                       'location': 'Taipei, Taiwan', 'avatar': 2, 
                       'full_name': 'Miles Wang', 'gender': 1, 
                       'timezone': 'Asia/Taipei', 'id': 4163456, 'karma': 66.0},
                      user.fans['4163456'])
    self.assertEquals({'page_user': {
                         'page_title': u'\u79d1\u5b78\u3001open source '
                                       u'\u548c\u7db2\u8def', 
                         'uid': 3158525, 'full_name': 'pingooo', 'timezone': None, 
                         'id': 3158525, 'num_of_fans': 312, 
                         'display_name': 'pingooo', 'num_of_friends': 147, 
                         'use_dark_icons': False, 'theme': 'metal-theme', 
                         'date_of_birth': None, 'theme_db': 'metal-theme', 
                         'location': 'XD city, Taiwan', 'theme_fg': 'dark-theme', 
                         'recruited': 8, 'creature': 9, 'has_custom_theme': True, 
                         'relationship': 'not_saying', 'has_profile_image': 1, 
                         'karma_change': 0.01, 'nick_name': 'pingooo', 
                         'gender': 1, 'avatar': 0, 'karma': 95.05},
                       'session_user': None},
                      user.metadata)
    self.assertEquals({'full_name': 'pingooo',
                       'about_me': u'拼股？別儍了...<br /><br />我性向測驗的'
                                   u'延宕記憶力是零，如果因為忘記我們曾互相認識'
                                   u'而把你加成粉絲，請在我的噗上提醒我。',
                       'profile_views': 9281, 
                       'friends_invited': 8,
                       'plurks_posted': 1349,
                       'plurk_responses': 5715,
                       'member_since': 'Sep 2008',
                       'last_login': '28 Nov 2009'},
                      user.about)
    self._mocker.VerifyAll()

if __name__ == '__main__':
  unittest.main()
